/**
 *******************************************************************************
 * @brief       Provide a brief description of the module here (Single line).
 * 
 * @author      Ashwin Vijayakumar
 * 
 * @file        main.c
 * 
 * @version
 * 
 * @date        Aug 11, 2012 09:50:40 AM
 * 
 * @details     Provide a detailed description of the module here (Multi-line).
 * 
 * @pre         Mention any preconditions required to use this module.
 * 
 * @bug         List any bugs in this module.
 * 
 * @note        List any odd modes while using this module.
 * 
 * @warning     List any warnings against using the objects of this module.
 *******************************************************************************
 * @copyright 2012
 * <a href="http://www.afflatustech.com">Afflatus Techtronics</a>
 * and <a href="http://www.ashwinvijayakumar.co.nr">Ashwin Vijayakumar</a>
 * @n@n
 * This work is licensed under the Creative Commons
 * Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a copy
 * of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or
 * send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain
 * View, California, 94041, USA.
 *******************************************************************************
 */

/**@cond -----------------------------------------------------------------------
 * Includes section
 * Add all #include here.
 * ----------------------------------------------------------------- @endcond */

#pragma config OSC              = IRCIO67
#pragma config FCMEN            = OFF
#pragma config IESO             = OFF
#pragma config PWRT             = OFF
#pragma config BOREN            = OFF
#pragma config BORV             = 0
#pragma config WDT              = OFF
#pragma config WDTPS            = 32768
#pragma config PBADEN           = OFF
#pragma config LPT1OSC          = OFF
#pragma config MCLRE            = ON
#pragma config STVREN           = ON
#pragma config LVP              = OFF
#pragma config BBSIZ            = 1024
#pragma config XINST            = OFF
#pragma config DEBUG            = ON
#pragma config CP0              = OFF
#pragma config CP1              = OFF
#pragma config CP2              = OFF
#pragma config CP3              = OFF
#pragma config CP4              = OFF
#pragma config CP5              = OFF
#pragma config CPB              = OFF
#pragma config CPD              = OFF
#pragma config WRT1             = OFF
#pragma config WRT2             = OFF
#pragma config WRT3             = OFF
#pragma config WRT4             = OFF
#pragma config WRT5             = OFF
#pragma config WRTC             = OFF
#pragma config WRTB             = OFF
#pragma config WRTD             = OFF
#pragma config EBTR0            = OFF
#pragma config EBTR1            = OFF
#pragma config EBTR2            = OFF
#pragma config EBTR3            = OFF
#pragma config EBTR4            = OFF
#pragma config EBTR5            = OFF

/**@cond System headers -------------------------------------------- @endcond */
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <i2c.h>

/**@cond Local headers --------------------------------------------- @endcond */
#include "main.h"
#include "Bsp.h"
#include "McalMcu_conf.h"
#include "McalGpio.h"

#include "PalHd44780.h"
#include "PalHd44780_Fonts.h"
#include "PalDs1629.h"
#include "McalUart.h"
#include "Soft_Delay.h"
#include "time.h"
#include "EEP.h"
#include "TimeWp.h"
#include "PrintWp.h"
#include "inttostr.h"


/**@cond -----------------------------------------------------------------------
 * typedef section (File scope)
 * Add typedef's with file scope here.
 * Capitalization: Upper_Camel_Case.
 * Declare typedef's with project scope in main.h.
 * ----------------------------------------------------------------- @endcond */

/**
 * @brief Provide the enumerator's brief description here.
 * @details Provide the enumerators's detailed description here.
 */
typedef enum
{
  TIME_15X32,           /**< Provide enum value1's brief description here. */
  DATE_15X32,           /**< Provide enum value1's brief description here. */
  TEMP_15x32,           /**< Provide enum value2's brief description here. */
  TIME_15X16,           /**< Provide enum value3's brief description here. */
  TEMP_15x16,           /**< Provide enum value2's brief description here. */
  MARIO_ANIMATION       /**< Provide enum value2's brief description here. */
} Dinapak_FuncSwitchStateType;

/**@cond -----------------------------------------------------------------------
 * Constants section (File scope)
 * Add all constants with file scope here.
 * Capitalization: ALL_CAPS.
 * Note that all constants listed here are limited to this file scope.
 * For project wide scope, declare constants in main.h.
 * ----------------------------------------------------------------- @endcond */

/**@cond -----------------------------------------------------------------------
 * Macros section (File scope)
 * Add all macros with file scope here.
 * Capitalization: ALL_CAPS.
 * Note that all macros listed here are limited to this file scope.
 * For project wide scope, declare macros in main.h.
 * ----------------------------------------------------------------- @endcond */

/**@cond -----------------------------------------------------------------------
 * Global variables section (File scope)
 * Add global variables with file scope here. 
 * Capitalization: lower_case.
 * Declare them with 'static' keyword.
 * ----------------------------------------------------------------- @endcond */

static const rom char splash_msg[] = {"\n\r\
=======================================================\n\r\
AFFLATUS TECHTRONICS - Ashwin Vijayakumar\n\r\
USART test code for APP\n\r\
Serial port communication still rocks\n\r\
Type Ashwin is cool on the keyboard\n\r\
=======================================================\n\r\
"};

/**@cond -----------------------------------------------------------------------
 * Global variables section (Project scope)
 * PROJECT SCOPE G-VARIABLES ARE LIKE FORBIDDEN FRUIT. REFRAIN FROM USING THEM, 
 * DECLARE FILE SCOPE G-VARIABLES INSTEAD AND DEFINE GETTER/SETTER METHODS TO 
 * ACCESS THEM.
 * Add global variables with project scope here. 
 * Capitalization: lower_case.
 * Declare them without 'static' keyword.
 * Also declare these variables in main.h with 'extern' keyword.
 * ----------------------------------------------------------------- @endcond */

/**@cond -----------------------------------------------------------------------
 * Function prototypes section (File scope)
 * Add prototypes for all functions with file scope here. 
 * Capitalization: lower_Camel_Case.
 * Declare them with 'static' keyword.
 * For functions with project scope, declare the function prototype in 
 * main.h without 'static' keyword.
 * ----------------------------------------------------------------- @endcond */

 static void Dinapak_Hd44780Init( PalHd44780_ConfigType* Hd44780_ConfigTemp );
 static void Dinapak_Ds1629Init( PalDs1629_BreakdownTimeType* PalDs1629_BreakdownTimeTemp );
 static void Dinapak_Disp15x32Time( char* breakdownAscTime );
 static void Dinapak_Disp15x32Date( char* breakdownAscTime );
 static void Dinapak_Disp15x32Temp( char* breakdownAscTime );
 static void Dinapak_DispMarioAnimation( void );

/**@cond -----------------------------------------------------------------------
 * Getter/setter method section (Project scope)
 * Define getter/setter methods to provide project scope global access to file 
 * scope global variables. (AVOID USING THESE IF YOU HAVE THROUGHPUT ISSUES).
 * Capitalization: get_Camel_Case/is_Camel_Case/set_Camel_Case.
 * Declare the prototype for these functions in main.h. 
 * ----------------------------------------------------------------- @endcond */

/**@cond ***********************************************************************
 * TODO: Update all comment fields and delete this line.
 * MOD: For functions with project scope, remove 'static' keyword and declare
 * prototype in main.h
 * -------------------------------------------------------------------- @endcond
 * @fn          return_type function_name(TYPE parameter1, TYPE parameter2)
 * @return      Describe the function's return value here.
 * @param       parameter1 Describe the function's 1st parameter here.
 * @param       parameter2 Describe the function's 2nd parameter here.
 * @author      avijayak
 * @date        Aug 11, 2012, 9:54:45 AM
 * @brief	Provide a brief description of the module here (Single line).
 * @details	Provide a detailed description of the module here (Multi-line).
 * @pre         Mention any preconditions required to use this function.
 * @post        Mention any postcondition required to use this function.
 * @bug         List any bugs in this module.
 * @note        List any odd modes while using this function.
 * @warning     List any warnings against using the objects of this function.
 *******************************************************************************
 */

void
main( void )
{
  uint8_t i;
  char ascTempBuf[3];
  PalHd44780_ConfigType Hd44780_Config;
  struct tm timeBuf;
  char funcSwitchTimeout = 0;
  int previous_sec = 0;
  int eepPtr = 0;
  char msgBuf[41] = {0};
  char arcTemp[4] = {0};
  char* arcTemp_1 = NULL;
  uint8_t X, Y;
  char breakdownAscTime[26];
  Dinapak_FuncSwitchStateType funcSwitchState;
  Dinapak_FuncSwitchStateType current_state;
  Dinapak_FuncSwitchStateType previous_state;
  Std_BoolType timeUpdateFlag = FALSE;
  Std_BoolType dateUpdateFlag = FALSE;
  Std_BoolType tempUpdateFlag = FALSE;

  /* Set internal oscillator @ 8MHz */
  F_OSC_8MHZ;

  /* Initialize UART */
  McalUart_Init();

  /* Project specific HD44780 LCD initializations */
  Dinapak_Hd44780Init( &Hd44780_Config );

  /* Initialize C18 I2C library */
  OpenI2C( MASTER, SLEW_OFF );

  /* I2C speed select [100KHz @ 8MHz = 14h] */
  SSPADD = 0x14;

  /* Project specific Ds1629 initializations */
  Dinapak_Ds1629Init( (PalDs1629_BreakdownTimeType*)&timeBuf );

  /* UART console splash print */
  McalUart_Putc( 0x0C );
  McalUart_Putrs( splash_msg );

  /* Repeat forever */
  while(1)
    {
      TimeWp_GetTime( &timeBuf );
      TimeWp_GetDate( &timeBuf );
      asctime_r( (const struct tm *)&timeBuf, breakdownAscTime );

      /* Update Time & Temperature only if seconds value has changed */
      if( previous_sec !=  timeBuf.tm_sec )
        {
          previous_sec = timeBuf.tm_sec;

          funcSwitchTimeout++;
          /* Display Time */
          if( ( funcSwitchTimeout >= 0 ) && ( funcSwitchTimeout < 10 ) )
            {
              timeUpdateFlag = TRUE;
              previous_state = current_state;
              current_state = TIME_15X32;
            }
          else if( ( funcSwitchTimeout >= 10) && ( funcSwitchTimeout < 15 ) )
            {
              dateUpdateFlag = TRUE;
              previous_state = current_state;
              current_state = DATE_15X32;
            }
          else if( ( funcSwitchTimeout >= 15) && ( funcSwitchTimeout < 20 ) )
            {
              tempUpdateFlag = TRUE;
              previous_state = current_state;
              current_state = TEMP_15x32;
            }
          else if( (funcSwitchTimeout >= 20) && (funcSwitchTimeout < 30) )
            {
              previous_state = current_state;
              current_state = MARIO_ANIMATION;
            }
          else
            {
              funcSwitchTimeout = 0;
            }
        }

      switch( current_state )
      {
      case TIME_15X32:
        if( TRUE == timeUpdateFlag )
          {
            timeUpdateFlag = FALSE;

            if( TIME_15X32 != previous_state )
              PalHd44780_ClearDisplay();
            Dinapak_Disp15x32Time( breakdownAscTime );
          }
        break;
      case DATE_15X32:
        if( TRUE == dateUpdateFlag )
          {
            dateUpdateFlag = FALSE;

            if( DATE_15X32 != previous_state )
              PalHd44780_ClearDisplay();
            Dinapak_Disp15x32Date( breakdownAscTime );
          }
        break;
      case TEMP_15x32:
        if( TRUE == tempUpdateFlag )
          {
            tempUpdateFlag = FALSE;

            if( TEMP_15x32 != previous_state )
              PalHd44780_ClearDisplay();
            PalDs1629_GetAscTemp( ascTempBuf );
            Dinapak_Disp15x32Temp( ascTempBuf );
          }
        break;
      case MARIO_ANIMATION:
        if( MARIO_ANIMATION != previous_state )
          PalHd44780_ClearDisplay();
        Dinapak_DispMarioAnimation();
        break;
      }
    }
}

/** End of main ********************* Copyright (C) 2012 Afflatus Techtronics */


/* Project specific HD44780 LCD initializations *******************************/
static void
Dinapak_Hd44780Init( PalHd44780_ConfigType* Hd44780_ConfigTemp )
{
  /* Set I/O direction for pins connected to the LCD */
  McalGpio_SetPinDirection(PAL_HD44780_CTRL_DIR, PAL_HD44780_VEE, GPIO_PIN_OUT);
  McalGpio_ResetPins(PAL_HD44780_CTRL_PORT, PAL_HD44780_VEE);

  McalGpio_SetPinDirection(PAL_HD44780_BKLT_DIR, PAL_HD44780_BKLT_PIN, GPIO_PIN_OUT);
  McalGpio_ResetPins(PAL_HD44780_BKLT_PORT, PAL_HD44780_BKLT_PIN);

  /* Clear the configuration byte/register */
  Hd44780_ConfigTemp->byte = 0;

  /* Prep H44780 LCD configuration register */
  Hd44780_ConfigTemp->bit.shift      = FALSE;
  Hd44780_ConfigTemp->bit.increment  = TRUE;
  Hd44780_ConfigTemp->bit.blink      = FALSE;
  Hd44780_ConfigTemp->bit.cursor     = FALSE;
  Hd44780_ConfigTemp->bit.font       = PAL_HD44780_5x8_FONT;
  Hd44780_ConfigTemp->bit.lines      = PAL_HD44780_TWO_LINE;

  PalHd44780_Init( Hd44780_ConfigTemp );
  //PalHd44780_LoadCustomFont( PalHd44780_15x16FontPlot, 8 );
  PalHd44780_ClearDisplay();
}

/* Project specific DS1629 initializations ************************************/
static void
Dinapak_Ds1629Init( PalDs1629_BreakdownTimeType* PalDs1629_BreakdownTimeTemp )
{
  PalDs1629_BreakdownTimeTemp->tm_sec = 10;
  PalDs1629_BreakdownTimeTemp->tm_min = 54;
  PalDs1629_BreakdownTimeTemp->tm_hour = 6;
  PalDs1629_BreakdownTimeTemp->tm_wday = 1;
  PalDs1629_BreakdownTimeTemp->tm_mday = 23;
  PalDs1629_BreakdownTimeTemp->tm_mon = 9;
  PalDs1629_BreakdownTimeTemp->tm_year = 112;

  PalDs1629_SetHourMode( _12_HOUR );
  PalDs1629_SetTime( PalDs1629_BreakdownTimeTemp );
  PalDs1629_SetDate( PalDs1629_BreakdownTimeTemp );
}

static void
Dinapak_Disp15x32Time( char* breakdownAscTime )
{
  uint8_t i;

  PalHd44780_LoadCustomFont( PalHd44780_15x16FontPlot, 8 );

  PalHd44780_GoToXY( 0, 0 );

  /* Display Time on Line 0 */
  for( i = 11; i < 19; i++ )
    {
      PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, breakdownAscTime[i] );
    }
}

static void
Dinapak_Disp15x32Date( char* breakdownAscTime )
{
  uint8_t i;

  PalHd44780_LoadCustomFont( PalHd44780_15x16FontPlot, 8 );

  PalHd44780_GoToXY( 0, 0 );

  /* Display Day of Week on Line 0 */
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, ' ' );
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, breakdownAscTime[0] );
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, ( breakdownAscTime[1] - 32 ) );
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, ( breakdownAscTime[2] - 32 ) );

  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, ' ' );
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, ' ' );

  /* Display Day of Month on Line 0 */
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, ' ' );
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, breakdownAscTime[8] );
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, breakdownAscTime[9] );
}

static void
Dinapak_Disp15x32Temp( char* ascTemp )
{
  int i;

  PalHd44780_LoadCustomFont( PalHd44780_15x16FontPlot, 8 );

  PalHd44780_GoToXY( 0, 0 );
#if 0
  PrintWp_UiMsg( arcTemp, PRINT_DEVICE_ID_UART0 );

  /* Display Temperature */
  for( i = 0; i < 2; i++ )
    {
      PalHd44780_Putc( *arcTemp_1++ );
    }
  arcTemp_1 -= 2;
#endif
  /* Display Temperature */
  for( i = 0; i < 2; i++ )
    {
      PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, ascTemp[i] );
    }
  PalHd44780_15x32Putc( PalHd44780_15x32FontIndex, 'C' );
}

static void
Dinapak_DispMarioAnimation( void )
{
  static uint8_t animate_row = 0;
  static uint8_t animate_column = 0;
  static uint8_t animate_index_ctr = 0;

  PalHd44780_LoadCustomFont( PalHd44780_MarioRunRightIndex[animate_index_ctr], 6 );

  PalHd44780_ClearLine(animate_row);
  PalHd44780_ClearLine(animate_row + 1);

  PalHd44780_GoToXY( animate_row, animate_column );
  PalHd44780_Putc(0);
  PalHd44780_Putc(1);
  PalHd44780_Putc(2);
  PalHd44780_GoToXY( ( animate_row + 1 ), animate_column );
  PalHd44780_Putc(3);
  PalHd44780_Putc(4);
  PalHd44780_Putc(5);

  if( ++animate_index_ctr > 2 )
    animate_index_ctr = 0;

  if( ++animate_column > (PAL_HD44780_NO_OF_COLUMNS - 3) )
    {
      animate_row += 2;
      if( animate_row >= 4)
        animate_row = 0;

      animate_column = 0;
    }
}

/** END OF FILE ********************* Copyright (C) 2012 Afflatus Techtronics */
